#include <stdio.h>
#include "/home/ye/jpeglib/include/jpeglib.h"
#include <setjmp.h>
#include "font.h"

struct my_error_mgr
{
  struct jpeg_error_mgr pub; /* "public" fields */
  jmp_buf setjmp_buffer;     /* for return to caller */
};
typedef struct my_error_mgr *my_error_ptr;

METHODDEF(void)
my_error_exit(j_common_ptr cinfo)
{
  my_error_ptr myerr = (my_error_ptr)cinfo->err;
  (*cinfo->err->output_message)(cinfo);
  longjmp(myerr->setjmp_buffer, 1);
}

// jpeg 解压例子
int read_JPEG_file(char *filename, void *map_addr, int px, int py)
{
  // 定义jpeg解码结构体
  struct jpeg_decompress_struct cinfo;

  // 定义错误处理结构体
  struct my_error_mgr jerr;
  /* More stuff */
  FILE *infile;      /* source file  源文件*/
  JSAMPARRAY buffer; /* Output row buffer  输出行缓存*/
  int row_stride;    /* physical row width in output buffer  行缓存宽度*/

  // 打开jpeg解码源文件
  if ((infile = fopen(filename, "rb")) == NULL)
  {
    fprintf(stderr, "can't open %s\n", filename);
    return 0;
  }

  /* Step 1: 分配并初始化jpeg解码对象 */
  /* 注册错误处理程序 */
  cinfo.err = jpeg_std_error(&jerr.pub);
  jerr.pub.error_exit = my_error_exit;
  /* Establish the setjmp return context for my_error_exit to use. */
  if (setjmp(jerr.setjmp_buffer))
  {
    jpeg_destroy_decompress(&cinfo);
    fclose(infile);
    return 0;
  }

  /* 初始化解码对象 */
  jpeg_create_decompress(&cinfo);

  /* Step 2: 指定需要解码的源文件*/
  jpeg_stdio_src(&cinfo, infile);

  /* Step 3: 读取jpeg图片头信息 */

  (void)jpeg_read_header(&cinfo, TRUE);

  /* Step 4: set parameters for decompression 设置解压参数*/
  /* Step 5: 开始解压jpeg图像 */
  (void)jpeg_start_decompress(&cinfo);

  // 设置输出缓存区的大小
  /*  cinfo.output_width 图像的宽度  * cinfo.output_components 图像色深   */
  row_stride = cinfo.output_width * cinfo.output_components;
  buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr)&cinfo, JPOOL_IMAGE, row_stride, 1);

  int y = 0; // 当前解码行

  // 获取宽度和高度
  int w = cinfo.output_width;        // 宽度
  int h = cinfo.output_height;       // 高度
  int bit = cinfo.output_components; // 色深

  printf("图片名称 %s 宽度 %d 高度 %d 色深%d\n", filename, cinfo.output_width, cinfo.output_height, bit);

  // 根据图片的大小定义缓存区
  char rgb[w * h * bit]; // 所有像素都存储到 rgb中

  // cinfo.output_scanline 输出行   cinfo.output_height 图像高度
  while (cinfo.output_scanline < cinfo.output_height)
  {
    // ✨读取一行jpeg解码数据到 buffer
    (void)jpeg_read_scanlines(&cinfo, buffer, 1);
    // printf("当前解码行%d\n", cinfo.output_scanline);
    for (int i = 0; i < w * bit; i++)
    {
      rgb[i + w * bit * y] = buffer[0][i];
    }
    y++; // 跳到下一行
  }


  // 把rgb 转换为 argb
  char argb[w * h * 4];

  for (int i = 0; i < w * h; i++)
  {
    argb[3 + i * 4] = 0;
    argb[2 + i * 4] = rgb[0 + i * bit];
    argb[1 + i * 4] = rgb[1 + i * bit];
    argb[0 + i * 4] = rgb[2 + i * bit];
  }

  // 把像素点放入映射地址
  // 把 argb 放入映射地址
  int (*lcd)[800] = map_addr;
  int (*color)[w] = (void *)argb;

  for (int y = 0; y < h; y++)
  {
    for (int x = 0; x < w; x++)
    {
      if (x + px < 800 && y + py < 480) // 在范围内的点才显示，防止越界
      {
        lcd[y + py][x + px] = color[y][x];
      }
    }
  }

  

  /* Step 7: 结束解码 */
  (void)jpeg_finish_decompress(&cinfo);

  /* Step 8: 销毁解码对象 */
  /* This is an important step since it will release a good deal of memory. */
  jpeg_destroy_decompress(&cinfo);

  // 关闭文件
  fclose(infile);

  /* And we're done! */
  return 1;
}